import 'package:flutter/foundation.dart';
import 'dart:async';
import '../models/server_config.dart';
import '../models/traffic_stats.dart';
import '../services/vpn_service.dart';
import '../services/storage_service.dart';
import '../services/ip_location_service.dart';
import '../services/log_service.dart';

enum VpnStatus { disconnected, connecting, connected, disconnecting }

enum ServerSortMode { recent, ping, name }

class VpnProvider with ChangeNotifier {
  final VpnService _vpnService = VpnService();
  final StorageService _storageService = StorageService();
  final IpLocationService _ipLocationService = IpLocationService();
  final LogService _logService = LogService();

  VpnStatus _status = VpnStatus.disconnected;
  ServerConfig? _currentServer;
  List<ServerConfig> _servers = [];
  TrafficStats? _currentStats;
  List<TrafficStats> _statsHistory = [];
  Timer? _statsTimer;
  
  String _searchQuery = '';
  String _selectedGroup = 'All';
  bool _showFavoritesOnly = false;
  ServerSortMode _sortMode = ServerSortMode.recent;
  
  DateTime? _connectionStartTime;
  Duration _connectionDuration = Duration.zero;
  Timer? _durationTimer;
  
  // 本机IP位置信息（连接前）
  IpLocationInfo? _originalLocation;
  bool _isLoadingOriginalLocation = false;
  
  // 代理IP位置信息（连接后）
  IpLocationInfo? _proxyLocation;
  bool _isLoadingProxyLocation = false;

  String? _testingPingServerId;
  String? get testingPingServerId => _testingPingServerId;

  VpnStatus get status => _status;
  ServerConfig? get currentServer => _currentServer;
  List<ServerConfig> get servers => _filteredServers;
  List<ServerConfig> get allServers => _servers; // 获取所有未过滤的服务器
  TrafficStats? get currentStats => _currentStats;
  List<TrafficStats> get statsHistory => _statsHistory;
  
  String get searchQuery => _searchQuery;
  String get selectedGroup => _selectedGroup;
  bool get showFavoritesOnly => _showFavoritesOnly;
  ServerSortMode get sortMode => _sortMode;
  Duration get connectionDuration => _connectionDuration;
  
  // 本机IP位置信息
  IpLocationInfo? get originalLocation => _originalLocation;
  bool get isLoadingOriginalLocation => _isLoadingOriginalLocation;
  String get originalCountryFlag => _originalLocation != null 
      ? _ipLocationService.getCountryFlag(_originalLocation!.countryCode)
      : '🌍';
  
  // 代理IP位置信息
  IpLocationInfo? get proxyLocation => _proxyLocation;
  bool get isLoadingProxyLocation => _isLoadingProxyLocation;
  String get proxyCountryFlag => _proxyLocation != null 
      ? _ipLocationService.getCountryFlag(_proxyLocation!.countryCode)
      : '🌍';

  List<String> get groups {
    final groups = _servers.map((s) => s.group ?? 'Default').toSet().toList();
    groups.sort();
    return ['All', ...groups];
  }

  List<ServerConfig> get _filteredServers {
    var filtered = _servers;

    if (_selectedGroup != 'All') {
      filtered = filtered.where((s) => s.group == _selectedGroup).toList();
    }

    if (_showFavoritesOnly) {
      filtered = filtered.where((s) => s.isFavorite).toList();
    }

    if (_searchQuery.isNotEmpty) {
      filtered = filtered.where((s) {
        return s.name.toLowerCase().contains(_searchQuery.toLowerCase()) ||
            s.address.toLowerCase().contains(_searchQuery.toLowerCase()) ||
            (s.remarks?.toLowerCase().contains(_searchQuery.toLowerCase()) ?? false);
      }).toList();
    }

    // Apply sorting based on sort mode with stable sorting
    // Use server ID as secondary sort key to prevent jumping
    switch (_sortMode) {
      case ServerSortMode.ping:
        filtered.sort((a, b) {
          // -1 means not tested, put them at the end
          if (a.ping == -1 && b.ping == -1) {
            return a.id.compareTo(b.id); // Stable sort: use ID when both untested
          }
          if (a.ping == -1) return 1;
          if (b.ping == -1) return -1;
          
          final pingCompare = a.ping.compareTo(b.ping);
          if (pingCompare != 0) return pingCompare;
          return a.id.compareTo(b.id); // Stable sort: use ID when ping is same
        });
        break;
      case ServerSortMode.name:
        filtered.sort((a, b) {
          final nameCompare = a.name.compareTo(b.name);
          if (nameCompare != 0) return nameCompare;
          return a.id.compareTo(b.id); // Stable sort: use ID when name is same
        });
        break;
      case ServerSortMode.recent:
        filtered.sort((a, b) {
          if (a.lastUsed == null && b.lastUsed == null) {
            return a.id.compareTo(b.id); // Stable sort: use ID when both have no lastUsed
          }
          if (a.lastUsed == null) return 1;
          if (b.lastUsed == null) return -1;
          
          final lastUsedCompare = b.lastUsed!.compareTo(a.lastUsed!);
          if (lastUsedCompare != 0) return lastUsedCompare;
          return a.id.compareTo(b.id); // Stable sort: use ID when lastUsed is same
        });
        break;
    }

    return filtered;
  }

  VpnProvider() {
    _loadServers();
    _fetchOriginalIpLocation();
  }

  Future<void> _loadServers() async {
    _servers = await _storageService.loadServers();
    notifyListeners();
  }

  Future<void> addServer(ServerConfig server) async {
    _servers.add(server);
    await _storageService.saveServers(_servers);
    notifyListeners();
  }

  Future<void> updateServer(ServerConfig server) async {
    final index = _servers.indexWhere((s) => s.id == server.id);
    if (index != -1) {
      _servers[index] = server;
      await _storageService.saveServers(_servers);
      notifyListeners();
    }
  }

  Future<void> deleteServer(String serverId) async {
    _servers.removeWhere((s) => s.id == serverId);
    await _storageService.saveServers(_servers);
    notifyListeners();
  }

  /// Delete all servers belonging to a specific group
  Future<void> deleteServersByGroup(String groupName) async {
    final removedCount = _servers.where((s) => s.group == groupName).length;
    _servers.removeWhere((s) => s.group == groupName);
    
    if (removedCount > 0) {
      await _storageService.saveServers(_servers);
      notifyListeners();
      print('🗑️ Deleted $removedCount servers from group "$groupName"');
    }
  }

  Future<void> toggleFavorite(String serverId) async {
    final index = _servers.indexWhere((s) => s.id == serverId);
    if (index != -1) {
      _servers[index] = _servers[index].copyWith(
        isFavorite: !_servers[index].isFavorite,
      );
      await _storageService.saveServers(_servers);
      notifyListeners();
    }
  }

  Future<void> togglePin(String serverId) async {
    final index = _servers.indexWhere((s) => s.id == serverId);
    if (index != -1) {
      _servers[index] = _servers[index].copyWith(
        isPinned: !_servers[index].isPinned,
      );
      await _storageService.saveServers(_servers);
      notifyListeners();
    }
  }

  void setSearchQuery(String query) {
    _searchQuery = query;
    notifyListeners();
  }

  void setSortMode(ServerSortMode mode) {
    _sortMode = mode;
    notifyListeners();
  }

  void setSelectedGroup(String group) {
    _selectedGroup = group;
    notifyListeners();
  }

  void toggleFavoritesOnly() {
    _showFavoritesOnly = !_showFavoritesOnly;
    notifyListeners();
  }

  /// 清除所有服务器的最近使用历史
  Future<void> clearRecentHistory() async {
    for (var i = 0; i < _servers.length; i++) {
      if (_servers[i].lastUsed != null) {
        _servers[i] = _servers[i].copyWith(lastUsed: null);
      }
    }
    await _storageService.saveServers(_servers);
    notifyListeners();
  }

  Future<void> connect(ServerConfig server) async {
    if (_status == VpnStatus.connected || _status == VpnStatus.connecting) {
      _logService.warning('Connection already in progress or established', category: 'connection');
      return;
    }

    _logService.info('Initiating VPN connection to ${server.name}...', category: 'connection');
    _status = VpnStatus.connecting;
    _currentServer = server;
    notifyListeners();

    try {
      _logService.debug('Server details: ${server.address}:${server.port}', category: 'connection');
      await _vpnService.connect(server);
      
      _status = VpnStatus.connected;
      _connectionStartTime = DateTime.now();
      _startStatsTimer();
      _startDurationTimer();
      
      _logService.info('VPN connection established successfully', category: 'connection');
      _logService.info('Connected to server: ${server.name}', category: 'connection');
      
      // Fetch IP location after connection
      _fetchIpLocation();
    } catch (e) {
      _logService.error('Failed to connect: $e', category: 'connection');
      _status = VpnStatus.disconnected;
      _currentServer = null;
      _connectionStartTime = null;
      rethrow;
    }

    notifyListeners();
  }

  Future<void> disconnect() async {
    if (_status == VpnStatus.disconnected || _status == VpnStatus.disconnecting) {
      _logService.warning('No active connection to disconnect', category: 'connection');
      return;
    }

    _logService.info('Disconnecting VPN...', category: 'connection');

    // 保存当前连接的服务器，用于更新 lastUsed
    final serverToUpdate = _currentServer;

    _status = VpnStatus.disconnecting;
    notifyListeners();

    try {
      await _vpnService.disconnect();
      _stopStatsTimer();
      _stopDurationTimer();
      
      // Update last used time when disconnecting (避免连接时列表跳动)
      if (serverToUpdate != null) {
        final index = _servers.indexWhere((s) => s.id == serverToUpdate.id);
        if (index != -1) {
          _servers[index] = _servers[index].copyWith(lastUsed: DateTime.now());
          await _storageService.saveServers(_servers);
        }
      }
      
      _status = VpnStatus.disconnected;
      _currentServer = null;
      _currentStats = null;
      _connectionStartTime = null;
      _connectionDuration = Duration.zero;
      _proxyLocation = null;
      _isLoadingProxyLocation = false;
      
      _logService.info('VPN disconnected', category: 'connection');
    } catch (e) {
      _logService.error('Failed to disconnect: $e', category: 'connection');
      _status = VpnStatus.connected;
      rethrow;
    }

    notifyListeners();
  }

  void _startStatsTimer() {
    _statsTimer?.cancel();
    _statsTimer = Timer.periodic(const Duration(seconds: 1), (timer) async {
      final stats = await _vpnService.getTrafficStats();
      _currentStats = stats;
      _statsHistory.add(stats);
      
      // Keep only last 60 data points
      if (_statsHistory.length > 60) {
        _statsHistory.removeAt(0);
      }
      
      // 每10秒记录一次流量统计
      if (_statsHistory.length % 10 == 0) {
        final upload = (stats.uploadSpeed / 1024 / 1024).toStringAsFixed(2);
        final download = (stats.downloadSpeed / 1024 / 1024).toStringAsFixed(2);
        _logService.debug(
          'Upload: $upload MB/s, Download: $download MB/s',
          category: 'traffic',
        );
      }
      
      notifyListeners();
    });
  }

  void _stopStatsTimer() {
    _statsTimer?.cancel();
    _statsTimer = null;
    _statsHistory.clear();
  }

  void _startDurationTimer() {
    _durationTimer?.cancel();
    _durationTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
      if (_connectionStartTime != null) {
        _connectionDuration = DateTime.now().difference(_connectionStartTime!);
        notifyListeners();
      }
    });
  }

  void _stopDurationTimer() {
    _durationTimer?.cancel();
    _durationTimer = null;
  }

  Future<void> _fetchOriginalIpLocation() async {
    _isLoadingOriginalLocation = true;
    notifyListeners();
    
    _logService.debug('Fetching original IP location...', category: 'system');
    
    try {
      final location = await _ipLocationService.getLocationInfo();
      _originalLocation = location;
      if (location != null) {
        _logService.info(
          'Original location: ${location.country} (${location.city})',
          category: 'system',
        );
      }
    } catch (e) {
      _logService.warning('Failed to fetch original IP location: $e', category: 'system');
      print('Error fetching original IP location: $e');
      _originalLocation = null;
    } finally {
      _isLoadingOriginalLocation = false;
      notifyListeners();
    }
  }

  Future<void> _fetchIpLocation() async {
    _isLoadingProxyLocation = true;
    notifyListeners();
    
    _logService.debug('Fetching proxy IP location...', category: 'system');
    
    try {
      // Wait a bit for connection to stabilize
      await Future.delayed(const Duration(seconds: 2));
      
      // 如果当前连接的服务器已有位置信息，直接使用
      if (_currentServer != null && 
          _currentServer!.country != null && 
          _currentServer!.countryCode != null) {
        // 使用服务器的位置信息创建IpLocationInfo
        _proxyLocation = IpLocationInfo(
          query: _currentServer!.address,
          country: _currentServer!.country!,
          countryCode: _currentServer!.countryCode!,
          city: _currentServer!.city ?? '',
          region: '',
          regionName: '',
          zip: '',
          timezone: '',
          isp: '',
          org: '',
          as: '',
          lat: 0,
          lon: 0,
        );
        _logService.info(
          'Proxy location: ${_proxyLocation!.country} (${_proxyLocation!.city})',
          category: 'system',
        );
      } else {
        // 否则获取实际IP位置
        final location = await _ipLocationService.getLocationInfo();
        _proxyLocation = location;
        if (location != null) {
          _logService.info(
            'Proxy location: ${location.country} (${location.city})',
            category: 'system',
          );
        }
      }
    } catch (e) {
      _logService.warning('Failed to fetch proxy IP location: $e', category: 'system');
      print('Error fetching proxy IP location: $e');
      _proxyLocation = null;
    } finally {
      _isLoadingProxyLocation = false;
      notifyListeners();
    }
  }

  Future<void> testPing(ServerConfig server) async {
    _testingPingServerId = server.id;
    notifyListeners();
    
    try {
      final ping = await _vpnService.testPing(server);
      final index = _servers.indexWhere((s) => s.id == server.id);
      if (index != -1) {
        // 同时获取服务器位置信息
        IpLocationInfo? location;
        try {
          location = await _ipLocationService.getLocationInfo(ip: server.address);
        } catch (e) {
          print('Error fetching server location for ${server.address}: $e');
        }
        
        _servers[index] = _servers[index].copyWith(
          ping: ping,
          country: location?.country,
          countryCode: location?.countryCode,
          city: location?.city,
        );
        await _storageService.saveServers(_servers);
        notifyListeners();
      }
    } finally {
      _testingPingServerId = null;
      notifyListeners();
    }
  }

  Future<void> testAllPings() async {
    for (var server in _servers) {
      await testPing(server);
    }
  }

  // 诊断服务器ID是否有重复
  void diagnoseServerIds() {
    final idMap = <String, List<ServerConfig>>{};
    
    for (var server in _servers) {
      idMap.putIfAbsent(server.id, () => []).add(server);
    }
    
    print('━━━ Server ID Diagnosis ━━━');
    int duplicates = 0;
    int totalServers = _servers.length;
    
    for (var entry in idMap.entries) {
      if (entry.value.length > 1) {
        duplicates++;
        print('❌ Duplicate ID: ${entry.key}');
        for (var server in entry.value) {
          print('   - ${server.name} (${server.address}:${server.port})');
        }
      }
    }
    
    print('───────────────────────');
    print('Total servers: $totalServers');
    print('Unique IDs: ${idMap.length}');
    
    if (duplicates == 0) {
      print('✅ All server IDs are unique!');
    } else {
      print('⚠️  Found $duplicates duplicate IDs affecting ${totalServers - idMap.length} servers!');
      print('💡 Run fixDuplicateIds() to fix this issue.');
    }
    print('━━━━━━━━━━━━━━━━━━━━━━━');
  }

  // 修复重复的服务器ID
  Future<void> fixDuplicateIds() async {
    final seenIds = <String>{};
    bool hasChanges = false;
    int fixedCount = 0;
    
    print('🔧 Starting ID fix...');
    
    for (int i = 0; i < _servers.length; i++) {
      if (seenIds.contains(_servers[i].id)) {
        // 生成新的唯一ID
        final oldId = _servers[i].id;
        final newId = _generateUniqueId();
        _servers[i] = _servers[i].copyWith(id: newId);
        hasChanges = true;
        fixedCount++;
        print('  Fixed: ${_servers[i].name}');
        print('    Old ID: $oldId');
        print('    New ID: $newId');
      } else {
        seenIds.add(_servers[i].id);
      }
    }
    
    if (hasChanges) {
      await _storageService.saveServers(_servers);
      notifyListeners();
      print('✅ Fixed $fixedCount duplicate IDs');
    } else {
      print('✓ No duplicate IDs found');
    }
  }

  // 生成唯一ID
  String _generateUniqueId() {
    final timestamp = DateTime.now().microsecondsSinceEpoch;
    final random = (timestamp * 31) % 1000000;
    return '${timestamp}_$random';
  }

  @override
  void dispose() {
    _stopStatsTimer();
    _stopDurationTimer();
    super.dispose();
  }
}
